package program.conditions;

import be.kuleuven.cs.som.annotate.*;
import item.*;

/**
 * A class for dealing with and-conditions: (and(condition)(condition)).  
 * 
 * @inar        The first condition of each and-condition must be valid.
 *                      | canHaveAsCondition(getFirstCondition())
 * @invar       The second condition of each and-condition must be valid.
 *                      | canHaveAsCondition(getSecondCondition())
 * 
 */
public class And extends Conditions {
	private final Conditions firstCondition;
	private final Conditions secondCondition;

	/**
	 * Initialise this new and-condition with a line number and two conditions.
	 * 
	 * @param       firstCondition
	 *                      The first condition to be evaluated.
	 * @param       secondCondition
	 *                      The second condition to be evaluated.
	 * @pre         The given first condition must be a valid one.
	 *                      | canHaveAsCondition(firstCondition)
	 * @pre         The given second condition must be a valid one.
	 *                      | canHaveAsCondition(secondCondition)
	 * @post        The first condition of this and-condition is set 
	 *                      to the given first condition.
	 *                      | new.getFirstCondition() == firstCondition
	 * @post        The second condition of this and-condition is set 
	 *                      to the given second condition.
	 *                      | new.getSecondCondition() == secondCondition
	 */
	public And(int lineNb, Conditions firstCondition, Conditions secondCondition) {
		super(lineNb);
		assert(canHaveAsConditions(firstCondition) );
		assert(canHaveAsConditions(secondCondition) );
		this.firstCondition = firstCondition;
		this.secondCondition = secondCondition;
	}

	/**
	 * Returns the first condition to be evaluated.
	 */
	@Basic @Raw @Immutable
	public Conditions getFirstCondition() {
		return firstCondition;
	}

	/**
	 * Return the second condition to be evaluated.
	 */
	@Basic @Raw @Immutable
	public Conditions getSecondCondition() {
		return secondCondition;
	}

	/**
	 * Checks whether the given conditions are valid for an and-condition.
	 * 
	 * @param	conditions
	 *          	The conditions to check for whether they are valid.
	 * @return      
	 * 			| result == conditions != null
	 */
	@Raw
	public boolean canHaveAsConditions(Conditions conditions) {
		return conditions != null;
	}

	/**
	 * Evaluates this condition for a given robot.
	 * 
	 * @return     
	 *          | result == (super.evaluate(robot) && getFirstCondition().evaluate(robot) && 
	 *          |   getSecondCondition().evaluate(robot) )
	 */
	@Override
	public boolean evaluate(Robot robot) {
		return super.evaluate(robot) &&	getFirstCondition().evaluate(robot) && 
				getSecondCondition().evaluate(robot);
	}

	/**
	 * Returns a textual representation of this and-condition, formatted in accordance with its position in the program.
	 * 
	 * @return      
	 * 			| result == getIndentation(indentationLevel) + "(and\n" + 
	 *          | 	getFirstCondition().prettyFormat(indentationLevel+1) + "\n" + 
	 *          |   getSecondCondition().prettyFormat(indentationLevel+1) + "\n)"
	 */
	@Override
	public String prettyFormat(int indentationLevel) {
		return getIndentation(indentationLevel) + "(and\n" + 
				getFirstCondition().prettyFormat(indentationLevel+1) + "\n" + 
				getSecondCondition().prettyFormat(indentationLevel+1) + "\n)";
	}
}